package com.linh.trade.gui;

import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.linh.trade.Operator;
import com.linh.trade.Output;
import com.linh.trade.Trader;
import com.linh.trade.TraderActionLog;
import com.linh.trade.algo.Strategy;
import com.linh.trade.algo.TrendFinder;
import com.linh.trade.algo.WindowBasedTrendFollower;
import com.linh.trade.algo.WindowMoverBySize;
import com.linh.trade.data.MarketData;
import com.linh.trade.data.MarketDataFromFile;
import com.linh.trade.data.NewPointListener;
import com.linh.trade.data.Point;
import com.linh.trade.valuation.Valuator;
import com.linh.trade.data.RandomMarketData;

public class TradingConsole extends JFrame implements NewPointListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private static final Logger LOG = LoggerFactory
			.getLogger(TradingConsole.class);

	private Valuator valuator;

	private MarketData marketData;

	// start button
	JButton startButton = new JButton("Start");
	JButton pauseButton = new JButton("Pause");

	public TradingConsole() throws HeadlessException {
		super();
		init();
	}

	void init() {
		valuator = new Valuator();
		setTitle("Xuan Linh Tran's Entry");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(800, 900);
		Container container = getContentPane();
		GridBagLayout gridBagLayout = new GridBagLayout();
		GridBagConstraints c = new GridBagConstraints();
		container.setLayout(gridBagLayout);

		// IO
		JPanel ioPanel = new JPanel();
		ioPanel.setSize(800, 100);
		c.gridx = 0;
		c.gridy = 0;
		c.gridheight = 1;
		c.gridwidth = 1;
		container.add(ioPanel, c);
		ioPanel.setBorder(BorderFactory.createTitledBorder("I/O"));
		// input
		ioPanel.add(new JLabel("Input File"));
		final JTextField inputFileField = new JTextField(15);
		inputFileField.setEditable(false);
		ioPanel.add(inputFileField);
		JButton inputButton = new JButton("Browser");
		ioPanel.add(inputButton);
		inputButton.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent event) {
				JFileChooser chooser = new JFileChooser();
				int ret = chooser.showOpenDialog(TradingConsole.this);
				if (ret == JFileChooser.APPROVE_OPTION) {
					inputFileField.setText(chooser.getSelectedFile()
							.getAbsolutePath());
				}
			}
		});

		// output
		ioPanel.add(new JLabel("Output File"));
		final JTextField outputFileField = new JTextField(15);
		outputFileField.setEditable(false);
		ioPanel.add(outputFileField);
		JButton outputButton = new JButton("Browser");
		ioPanel.add(outputButton);
		outputButton.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent event) {
				JFileChooser chooser = new JFileChooser();
				int ret = chooser.showSaveDialog(TradingConsole.this);
				if (ret == JFileChooser.APPROVE_OPTION) {
					outputFileField.setText(chooser.getSelectedFile()
							.getAbsolutePath());
				}
			}
		});
		// random
		final JCheckBox randomCheckBox = new JCheckBox("Use Random");
		ioPanel.add(randomCheckBox);

		// graph
		final Graph graph = new Graph(1000);
		c.fill = GridBagConstraints.BOTH;
		c.gridx = 0;
		c.gridy = 1;
		c.gridheight = 3;
		c.gridwidth = 1;
		c.weighty = 1;
		JPanel graphPanel = new JPanel();
		graphPanel.setBorder(BorderFactory.createTitledBorder("Rates"));
		graphPanel.add(graph);
		container.add(graphPanel, c);
		c.weighty = 0;
		// trader and report
		JPanel panel = new JPanel();
		panel.setSize(800, 200);
		panel.setLayout(new GridLayout(1, 2));
		c.gridx = 0;
		c.gridy = 4;
		c.gridheight = 2;
		c.gridwidth = 1;
		container.add(panel, c);
		// trader
		JPanel traderPanel = new JPanel();
		traderPanel.setBorder(BorderFactory.createTitledBorder("Trader"));
		panel.add(traderPanel);
		traderPanel.setLayout(new GridLayout(6, 2));
		traderPanel.add(new JLabel("Budget"));
		final JTextField budgetField = new JTextField("500000");
		traderPanel.add(budgetField);
		traderPanel.add(new JLabel("Max Amount per Trade"));
		final JTextField maxAmountField = new JTextField("50000");
		traderPanel.add(maxAmountField);
		traderPanel.add(new JLabel("Min Amount per Trade"));
		final JTextField minAmountField = new JTextField("5000");
		traderPanel.add(minAmountField);

		traderPanel.add(new JLabel("Max Loss (fraction of Notional)"));
		final JTextField maxLossField = new JTextField("0.0001");
		traderPanel.add(maxLossField);

		traderPanel.add(new JLabel("Take Profit at (fraction of Notional)"));
		final JTextField ripProfitField = new JTextField("0.001");
		traderPanel.add(ripProfitField);

		traderPanel.add(new JLabel("Hurdle"));
		final JTextField hurdleField = new JTextField("0.0001");
		traderPanel.add(hurdleField);

		// report and params
		JPanel rpPanel = new JPanel();
		rpPanel.setLayout(new GridLayout(2, 1));
		final ReportPanel reportPanel = new ReportPanel(valuator);
		rpPanel.add(reportPanel);
		// params
		JPanel paramPanel = new JPanel();
		paramPanel.setBorder(BorderFactory.createTitledBorder("Params"));
		// paramPanel.setLayout(new GridLayout(1, 2));
		paramPanel.add(new JLabel("Rate Speed (miliseconds)"));
		final JTextField rateSpeed = new JTextField("0", 10);
		rateSpeed.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent event) {
				if (marketData != null) {
					try {
						long interval = Long.parseLong(rateSpeed.getText());
						marketData.setInterval(interval);
					} catch (NumberFormatException ex) {
						JOptionPane.showMessageDialog(TradingConsole.this,
								"Error", ex.getMessage(),
								JOptionPane.ERROR_MESSAGE);
						LOG.error("Error in setting interval", ex);
					}
				}

			}
		});
		paramPanel.add(rateSpeed);
		rpPanel.add(paramPanel);
		panel.add(rpPanel);

		// action
		final Console console = new Console();
		console.setPreferredSize(new Dimension(800, 50));
		c.gridx = 0;
		c.gridy = 6;
		c.gridheight = 1;
		c.gridwidth = 1;
		container.add(console, c);

		JPanel buttonPanel = new JPanel();
		buttonPanel.add(startButton);
		buttonPanel.add(pauseButton);
		c.gridx = 0;
		c.gridy = 7;
		c.gridheight = 1;
		c.gridwidth = 1;
		container.add(buttonPanel, c);

		startButton.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent event) {
				String cmd = startButton.getText();
				if (cmd.startsWith("Start")) {

					try {
						double budget = Double.parseDouble(budgetField
								.getText());
						double maxAmount = Double.parseDouble(maxAmountField
								.getText());
						double minAmount = Double.parseDouble(minAmountField
								.getText());
						double maxLoss = Double.parseDouble(maxLossField
								.getText());
						double ripProfit = Double.parseDouble(ripProfitField
								.getText());
						double hurdleUnit = Double.parseDouble(hurdleField
								.getText());
						long interval = Long.parseLong(rateSpeed.getText());
						final String inputFile = inputFileField.getText();
						String outputFile = outputFileField.getText();
						Operator operator = new Operator(valuator, budget);
						final Output output = new Output(outputFile);
						TrendFinder trendFinder = new TrendFinder(
								new WindowMoverBySize(6));
						double hurdle = hurdleUnit
								* WindowBasedTrendFollower.HURDLE_UNIT;
						Strategy strategy = new WindowBasedTrendFollower(
								trendFinder, hurdle);
						Trader trader = new Trader(strategy, operator,
								valuator, maxAmount, minAmount,
								WindowBasedTrendFollower.HURDLE_UNIT, maxLoss,
								ripProfit);
						trader.addTraderActionListener(new TraderActionLog());
						trader.addTraderActionListener(output);
						trader.addTraderActionListener(console);
						trader.addTraderActionListener(graph);
						if (randomCheckBox.isSelected()) {
							marketData=new RandomMarketData();
						} else {
							marketData = new MarketDataFromFile(inputFile);
						}
						//trader must be first listener
						marketData.addListener(trader);
						marketData.addListener(reportPanel);
						marketData.addListener(graph);
						marketData.addListener(TradingConsole.this);
						marketData.setInterval(interval);
						new Thread(marketData).start();
						startButton.setText("Stop");

					} catch (Exception ex) {
						LOG.error("Error", ex);
						JOptionPane.showMessageDialog(TradingConsole.this,
								"Error " + ex.getMessage());
					}
				} else {
					marketData.setStop(true);
					startButton.setText("Start");
					pauseButton.setText("Pause");
					graph.clear();
					console.clear();
					valuator.clear();

				}
			}
		});

		pauseButton.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent event) {
				String cmd = pauseButton.getText();
				if (cmd.startsWith("Pause")) {
					marketData.setPause(true);
					pauseButton.setText("Resume");
				} else {
					pauseButton.setText("Pause");
					marketData.setPause(false);
				}

			}
		});

		pack();
		setVisible(true);
	}

	public static void main(String[] args) {
		new TradingConsole();
	}

	public void newPoint(Point p) {

	}

	public void endOfData() {
		startButton.doClick();
		pauseButton.setText("Pause");
		JOptionPane.showMessageDialog(this, "END of TRADING");

	}

}
